#include "napi/native_api.h"
#include <charconv>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <string>
#include "hilog/log.h"
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x3200 // 全局domain宏，标识业务领域
#define LOG_TAG "MY_TAG"  // 全局tag宏，标识模块日志tag
static napi_value Add(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    napi_valuetype valuetype1;
    napi_typeof(env, args[1], &valuetype1);

    double value0;
    napi_get_value_double(env, args[0], &value0);

    double value1;
    napi_get_value_double(env, args[1], &value1);

    napi_value sum;
    napi_create_double(env, value0 + value1, &sum);

    return sum;
}

static napi_value NAPI_Global_bufferBlendDivide(napi_env env, napi_callback_info info) {
    size_t argc = 5;
    napi_value args[5] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // 检查参数是否为ArrayBuffer

    void *base_data = nullptr;
    size_t baseByteLength = 0;
    // 获取ArrayBuffer的底层数据缓冲区和长度
    napi_get_arraybuffer_info(env, args[0], &base_data, &baseByteLength);


    void *overlay_data = nullptr;
    size_t overlayByteLength = 0;
    // 获取ArrayBuffer的底层数据缓冲区和长度
    napi_get_arraybuffer_info(env, args[1], &overlay_data, &overlayByteLength);


    double width;
    napi_get_value_double(env, args[2], &width);

    double height;
    napi_get_value_double(env, args[3], &height);

    bool gray;
    napi_get_value_bool(env, args[4], &gray);

    uint8_t *base_data_uint8 = (uint8_t *)base_data;
    uint8_t *overlay_data_uint8 = (uint8_t *)overlay_data;

    void *result_data = nullptr;

    napi_value bufferData;

    napi_create_arraybuffer(env, baseByteLength, &result_data, &bufferData);

    uint8_t *dataBuffer = (uint8_t *)result_data;

    
//     for (int index = 0; index < baseByteLength; index++) {
//         dataBuffer[index] = base_data_uint8[index];
//     }

    int color_index = 0;
    double contrast = 70;
    double sum = 0;
    double avg = 0;
    for (int height_index = 0; height_index < height; height_index++) {
        for (int width_index = 0; width_index < width; width_index++) {

            int ci = color_index * 4;
            int r_i = ci + 2;
            int g_i = ci + 1;
            int b_i = ci;
            int a_i = ci + 3;

            double base_r = base_data_uint8[r_i] / 255.0;
            double base_g = base_data_uint8[g_i] / 255.0;
            double base_b = base_data_uint8[b_i] / 255.0;
            double base_a = base_data_uint8[a_i] / 255.0;

            double overlay_r = overlay_data_uint8[r_i] / 255.0;
            double overlay_g = overlay_data_uint8[g_i] / 255.0;
            double overlay_b = overlay_data_uint8[b_i] / 255.0;
            double overlay_a = overlay_data_uint8[a_i] / 255.0;


            double ra = 0;
            if (overlay_a == 0.0 || ((base_r / overlay_r) > (base_a / overlay_a))) {
                ra = overlay_a * base_a + overlay_r * (1.0 - base_a) + base_r * (1.0 - overlay_a);
            } else {
                ra = (base_r * overlay_a * overlay_a) / overlay_r + overlay_r * (1.0 - base_a) +
                     base_r * (1.0 - overlay_a);
            }

            double ga = 0;
            if (overlay_a == 0.0 || ((base_g / overlay_g) > (base_a / overlay_a))) {
                ga = overlay_a * base_a + overlay_g * (1.0 - base_a) + base_g * (1.0 - overlay_a);
            } else {
                ga = (base_g * overlay_a * overlay_a) / overlay_g + overlay_g * (1.0 - base_a) +
                     base_g * (1.0 - overlay_a);
            }

            double ba = 0;
            if (overlay_a == 0.0 || ((base_b / overlay_b) > (base_a / overlay_a))) {
                ba = overlay_a * base_a + overlay_b * (1.0 - base_a) + base_b * (1.0 - overlay_a);
            } else {
                ba = (base_b * overlay_a * overlay_a) / overlay_b + overlay_b * (1.0 - base_a) +
                     base_b * (1.0 - overlay_a);
            }


            // R
            base_data_uint8[r_i] = (int)(ra * 255.0);
            dataBuffer[r_i] = base_data_uint8[r_i];

            // G

            base_data_uint8[g_i] = (int)(ga * 255.0);
            dataBuffer[g_i] = base_data_uint8[g_i];

            // B
            base_data_uint8[b_i] = (int)(ba * 255.0);
            dataBuffer[b_i] = base_data_uint8[b_i];

            // A
            double a = overlay_a + base_a - overlay_a * base_a;
            base_data_uint8[a_i] = (int)(a * 255.0);
            dataBuffer[a_i] = base_data_uint8[a_i];

//             int agv = (dataBuffer[g_i] + dataBuffer[r_i] + dataBuffer[b_i]) / 3;
//            
//             if (agv < 240) {
//                 dataBuffer[g_i] = ( dataBuffer[g_i]-128) * 0.5 +128;
//                 dataBuffer[r_i] =  ( dataBuffer[r_i]-128) * 0.5 +128;
//                 dataBuffer[b_i] =  ( dataBuffer[b_i]-128) * 0.5 +128;
//             }
           
            double brightness = 0.3 * ba * 255 + 0.59 * ga * 255 + 0.11 * ra * 255;
            sum += brightness;
            color_index++;
        }
    }
    return bufferData;
    double v = (contrast - 50) * 2;
    avg = sum / (height * width);
    color_index = 0;
    for (int height_index = 0; height_index < height; height_index++) {
        for (int width_index = 0; width_index < width; width_index++) {
            int i = color_index * 4;
            int agv = (dataBuffer[i] + dataBuffer[i + 1] + dataBuffer[i + 2]) / 3;
            // 100   248
            int lagv = 100;
            if (gray) {
                lagv = 243;
            }
//             if (agv < lagv) {
//                 dataBuffer[i] = dataBuffer[i] * 0.1;
//                 dataBuffer[i + 1] = dataBuffer[i + 1] * 0.1;
//                 dataBuffer[i + 2] = dataBuffer[i + 2] * 0.1;
//             }
            if (agv < 248) {
                dataBuffer[i] = 255;
                dataBuffer[i + 1] = 255;
                dataBuffer[i + 2] = 255;
            }
            
            
//             if (agv<180) {
//                 dataBuffer[i] = dataBuffer[i] * 0.1;
//                 dataBuffer[i + 1] = dataBuffer[i + 1] * 0.1;
//                 dataBuffer[i + 2] = dataBuffer[i + 2] * 0.1;
//             }
            
//             if (dataBuffer[i] < 50 && dataBuffer[i+1] < 50&& dataBuffer[i+2] < 50 ) {
//                 dataBuffer[i] = 0;
//                    dataBuffer[i+1] =0;
//                   dataBuffer[i+2] = 0;
//             }
            
//             if (dataBuffer[i] < 200 ) {
//                 dataBuffer[i] =0;
//             }
//             if (dataBuffer[i+1] < 200 ) {
//                 dataBuffer[i+1] =0;
//             }
//             if (dataBuffer[i+2] < 200 ) {
//                 dataBuffer[i+2] = 0;
//             }

            color_index++;
        }
    }

    return bufferData;
}
static napi_value NAPI_Global_imageBufferGray(napi_env env, napi_callback_info info) {
    // TODO: implements the code;
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // 检查参数是否为ArrayBuffer

    void *base_data = nullptr;
    size_t baseByteLength = 0;
    // 获取ArrayBuffer的底层数据缓冲区和长度
    napi_get_arraybuffer_info(env, args[0], &base_data, &baseByteLength);

    double width;
    napi_get_value_double(env, args[1], &width);

    double height;
    napi_get_value_double(env, args[2], &height);

    void *result_data = nullptr;
    napi_value bufferData;
    napi_create_arraybuffer(env, baseByteLength, &result_data, &bufferData);
    uint8_t *dataBuffer = (uint8_t *)result_data;


    uint8_t *base_data_uint8 = (uint8_t *)base_data;
    int color_index = 0;
    for (int height_index = 0; height_index < height; height_index++) {
        for (int width_index = 0; width_index < width; width_index++) {
            int ci = color_index * 4;
            int r_i = ci + 2;
            int g_i = ci + 1;
            int b_i = ci;
            int a_i = ci + 3;
            double base_r = base_data_uint8[r_i];
            double base_g = base_data_uint8[g_i];
            double base_b = base_data_uint8[b_i];
            double base_a = base_data_uint8[a_i];
            color_index++;
            int max = base_r;
            if (max > base_g) {
                max = base_g;
            }
            if (max > base_b) {
                max = base_b;
            }
            dataBuffer[r_i] = max;
            dataBuffer[g_i] = max;
            dataBuffer[b_i] = max;
            dataBuffer[a_i] = base_a;
        }
    }
    return bufferData;
}
static napi_value NAPI_Global_imageBufferScanDocumentPosition(napi_env env, napi_callback_info info) {
    // TODO: implements the code;
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // 检查参数是否为ArrayBuffer

    void *base_data = nullptr;
    size_t baseByteLength = 0;
    // 获取ArrayBuffer的底层数据缓冲区和长度
    napi_get_arraybuffer_info(env, args[0], &base_data, &baseByteLength);

    double width;
    napi_get_value_double(env, args[1], &width);

    double height;
    napi_get_value_double(env, args[2], &height);

    // void *img_gray_data = nullptr;
    // napi_value bufferData;
    // napi_create_arraybuffer(env, baseByteLength, &result_data, &bufferData);
    // uint8_t *dataBuffer = (uint8_t *)img_gray_data;
    uint8_t *dataBuffer = (uint8_t *)malloc(sizeof(uint8_t) * baseByteLength);

    uint8_t *base_data_uint8 = (uint8_t *)base_data;
    int color_index = 0;
    for (int height_index = 0; height_index < height; height_index++) {
        for (int width_index = 0; width_index < width; width_index++) {
            int ci = color_index * 4;
            int r_i = ci + 2;
            int g_i = ci + 1;
            int b_i = ci;
            int a_i = ci + 3;
            double base_r = base_data_uint8[r_i];
            double base_g = base_data_uint8[g_i];
            double base_b = base_data_uint8[b_i];
            double base_a = base_data_uint8[a_i];
            color_index++;
            int max = base_r;
            if (max > base_g) {
                max = base_g;
            }
            if (max > base_b) {
                max = base_b;
            }
            dataBuffer[r_i] =  max;
            dataBuffer[g_i] = max;
            dataBuffer[b_i] =  max;
            dataBuffer[a_i] = base_a;
        }
    }
    napi_value result;
    napi_create_array(env, &result);
    for (int i = 0; i < 8; i++) {
        napi_value element;
        napi_create_int32(env, i, &element);
        napi_set_element(env, result, i, element);
    }
    color_index = 0;
    int a_wi = 0;
    int a_hi = 0;
    for (int height_index = 0; height_index < height; height_index++) {
        for (int width_index = 0; width_index < width; width_index++) {
            int fw = 100;

            // OH_LOG_ERROR(LOG_APP, "Pure color_index:%{public}d
            // w*h:%{public}d.",color_index,(height_index+1)*(width_index+1));


            int ci = color_index * 4;
            int r_i = ci + 2;
            int g_i = ci + 1;
            int b_i = ci;
            int a_i = ci + 3;
            double avg = (dataBuffer[r_i] + dataBuffer[g_i] + dataBuffer[b_i]) / 3.0;

            if (avg >= 200) {
                // 寻找左顶点

                int a_avg = 0;
                int b_avg = 0;
                int c_avg = 0;
                int d_avg = 0;
                int avg_sum=0;
                   int bvg_sum=0;
                   int cvg_sum=0;   int dvg_sum=0;

                for (int i_10 = 0; i_10 < fw; i_10++) {
                    //  左上 A
                    int ahi = height_index - (i_10);
                    int awi = width_index - (i_10);
                    if (ahi >= 0 && awi >= 0) {
                        int x = awi, y = ahi;
                        int wh_i = (y * width + x) * 4;
                        int wh_r_i = wh_i + 2;
                        int wh_g_i = wh_i + 1;
                        int wh_b_i = wh_i;
                        int wh_a_i = wh_i + 3;
                        // OH_LOG_ERROR(LOG_APP, "Pure a_avg:%{public}d ", (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] +
                        // dataBuffer[wh_b_i]) / 3);
                        a_avg = a_avg + (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] + dataBuffer[wh_b_i]) / 3;
                        avg_sum++;
                    }
                    // 右上B
                    int bhi = height_index - (i_10);
                    int bwi = width_index + (i_10);
                    if (bhi >= 0 && bwi >= 0) {
                        int x = bwi, y = bhi;
                        int wh_i = (y * width + x) * 4;
                        int wh_r_i = wh_i + 2;
                        int wh_g_i = wh_i + 1;
                        int wh_b_i = wh_i;
                        int wh_a_i = wh_i + 3;
                        // OH_LOG_ERROR(LOG_APP, "Pure a_avg:%{public}d ", (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] +
                        // dataBuffer[wh_b_i]) / 3);
                        b_avg = b_avg + (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] + dataBuffer[wh_b_i]) / 3;
                            bvg_sum++;
                    }

                    // 左下C  右下D
                    int chi = height_index + (i_10);
                    int cwi = width_index + (i_10);
                    if (chi >= 0 && cwi >= 0) {
                        int x = cwi, y = chi;
                        int wh_i = (y * width + x) * 4;
                        int wh_r_i = wh_i + 2;
                        int wh_g_i = wh_i + 1;
                        int wh_b_i = wh_i;
                        int wh_a_i = wh_i + 3;
                        // OH_LOG_ERROR(LOG_APP, "Pure a_avg:%{public}d ", (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] +
                        // dataBuffer[wh_b_i]) / 3);
                        c_avg = c_avg + (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] + dataBuffer[wh_b_i]) / 3;
                              cvg_sum++;
                    }
                    // 右下D
                    int dhi = height_index + (i_10);
                    int dwi = width_index - (i_10);
                    if (dhi >= 0 && dwi >= 0) {
                        int x = dwi, y = dhi;
                        int wh_i = (y * width + x) * 4;
                        int wh_r_i = wh_i + 2;
                        int wh_g_i = wh_i + 1;
                        int wh_b_i = wh_i;
                        int wh_a_i = wh_i + 3;
                        // OH_LOG_ERROR(LOG_APP, "Pure a_avg:%{public}d ", (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] +
                        // dataBuffer[wh_b_i]) / 3);
                        d_avg = d_avg + (dataBuffer[wh_r_i] + dataBuffer[wh_g_i] + dataBuffer[wh_b_i]) / 3;
                            dvg_sum++;
                    }
                }
                a_avg = a_avg / avg_sum;
                b_avg = b_avg / bvg_sum;
                c_avg = c_avg / cvg_sum;
                d_avg = d_avg / dvg_sum;
                if (a_wi == 0 && a_hi == 0) {
                    if (a_avg <100 && b_avg <100 && c_avg <100  && d_avg > 190) {
                        a_wi = width_index;
                        a_hi = height_index;
//                         OH_LOG_ERROR(
//                             LOG_APP,
//                             "Pure a_avg:%{public}d : %{public}d : %{public}d : %{public}d   xy = %{public}d,%{public}d",
//                             a_avg, b_avg, c_avg, d_avg, width_index, height_index);
                    }
                }
            }
            color_index++;
        }
    }


    return result;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"add2", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"imageBufferBlendDivide", nullptr, NAPI_Global_bufferBlendDivide, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"imageBufferGray", nullptr, NAPI_Global_imageBufferGray, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"imageBufferScanDocumentPosition", nullptr, NAPI_Global_imageBufferScanDocumentPosition, nullptr, nullptr,
         nullptr, napi_default, nullptr}};
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "mquery",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterMqueryModule(void) { napi_module_register(&demoModule); }
